package com.skyyan.netty.jjf.client;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.HexUtil;
import com.skyyan.netty.jjf.protocol.*;
import com.skyyan.netty.jjf.util.Str2HexUtils;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ScheduledFuture;

/**
 * 客户端业务逻辑处理器
 * 负责处理与服务器的通信逻辑，包括注册、心跳、业务请求等
 * @author skyyan
 */
public class ClientHandler extends SimpleChannelInboundHandler<Message> {

    private static final Logger log = LoggerFactory.getLogger(ClientHandler.class);

    private final byte[] clientAddress;
    private String regId;
    private boolean registered = false;
    //手持终端注册号数组（低位在前，高位在后）
    private byte[] regIdArr;

    private String deviceId;
    private ScheduledFuture<?> heartbeatTask;

    public ClientHandler(byte[] clientAddress) {
        this.clientAddress = clientAddress.clone();
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        log.info("成功连接到服务器: {}", ctx.channel().remoteAddress());

        // 连接成功后立即发送注册报文
//        sendRegisterMessage(ctx);

//        //regId="11223344556677889900AABBCCDDEEFF"
        String regId="11223344556677889900AABBCCDDEEFF";
        // 1. Hex字符串 → byte[]（默认：高位在前，大端序）
        byte[] bytes = HexUtil.decodeHex(regId.toCharArray());
        // 2. 反转字节数组 → 变成“低位在前”
        byte[] userData = ArrayUtil.reverse(bytes);
//
//        byte[] address=clientAddress;
//
//        RegisterConfirmMessage confirMsg=new RegisterConfirmMessage.Uplink(this.clientAddress,userData);
//        //注册确认
//        sengRegConfirm(ctx,confirMsg);

        //查询余额报文
//        sendBalanceQuery(ctx);
//        //开卡报文
//        try {
//            sendOpenCard(ctx);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }

    private void sendOpenCard(ChannelHandlerContext ctx) throws Exception {
        // 准备测试数据
        byte[] testAddress = new byte[]{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
                0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
                0x11, 0x12, 0x13, 0x14};

        String orderId = "1234567890123456";
        String name = "李四";
        String phone = "013812345678";
        String idCard = "110101199001011234";
        int areaCode = 1234;
        byte[] cardNo = new byte[]{0x01, 0x02, 0x03, 0x04, 0x05};

        // 测试上行报文组装
        System.out.println("测试上行报文组装和解析:");
        OpenCardMessage.Uplink uplink = new OpenCardMessage.Uplink(testAddress,  name, phone, idCard, areaCode, cardNo);
//
//        // 解析上行报文
//        OpenCardMessage.Uplink parsedUplink = new OpenCardMessage.Uplink(uplink.getAddress(), uplink.getUserData());

    }

    /**
     * 余额查询
     * @param ctx
     */
    private void BalanceQueryMessageTest(ChannelHandlerContext ctx) {
        System.out.println("1. 测试上行报文编码和解码:");

        try {
            // 使用16字节的设备注册号和int类型的设备序列号创建上行余额查询报文
            byte[] deviceRegId = new byte[16];
            // 设备注册号 (16字节，低位在前)
            for (int i = 0; i < 16; i++) {
                deviceRegId[i] = (byte) (i + 1);
            }

            int deviceSerialNo = 0x112233; // 示例设备序列号

            System.out.println("  原始参数:");
            System.out.println("    设备注册号(bytes): " + Str2HexUtils.bytesToHex(deviceRegId));
            System.out.println("    设备序列号(int): 0x" + String.format("%06X", deviceSerialNo));

            // 创建农户注册号 (16字节，低位在前)
            byte[] farmerRegId = new byte[16];
            for (int i = 0; i < 16; i++) {
                farmerRegId[i] = (byte) (i + 10);
            }

            System.out.println("  农户注册号: " + Str2HexUtils.bytesToHex(farmerRegId));

            // 创建上行余额查询报文
            BalanceQueryMessage.Uplink uplink = new BalanceQueryMessage.Uplink(deviceRegId, deviceSerialNo, farmerRegId);

            // 测试toString方法
            System.out.println("  Uplink.toString(): " + uplink.toString());

            // 获取提取的参数
            byte[] deviceRegIdBytes = uplink.getDeviceRegId();
            byte[] deviceSerialNoBytes = uplink.getDeviceSerialNo();
            int deviceSerialNoInt = uplink.getDeviceSerialNoInt();
            byte[] extractedFarmerRegId = uplink.getFarmerRegId();

            System.out.println("  提取的设备注册号(bytes): " + Str2HexUtils.bytesToHex(deviceRegIdBytes));
            System.out.println("  提取的设备序列号(bytes): " + Str2HexUtils.bytesToHex(deviceSerialNoBytes));
            System.out.println("  提取的设备序列号(int): 0x" + String.format("%06X", deviceSerialNoInt));
            System.out.println("  提取的农户注册号: " + Str2HexUtils.bytesToHex(extractedFarmerRegId));
            ctx.writeAndFlush(uplink);
            log.info("已发送余额查询报文");

        }catch (Exception ex){
            ex.printStackTrace();
        }

    }

    /**
     * 充值
     * @param ctx
     */
    public void RechargeMessageTest(ChannelHandlerContext ctx) {
        System.out.println("1. 测试上行报文编码和解码:");

        try {
            // 使用参数创建上行充值报文
            byte[] deviceRegId = new byte[16];
            // 设备注册号 (16字节，低位在前)
            for (int i = 0; i < 16; i++) {
                deviceRegId[i] = (byte) (i + 1);
            }

            int deviceSerialNo = 0x112233; // 示例设备序列号
            byte[] farmerRegId = new byte[16];
            // 农户注册号 (16字节，低位在前)
            for (int i = 0; i < 16; i++) {
                farmerRegId[i] = (byte) (i + 10);
            }

            int rechargeAmount = 10000; // 充值金额(单位为分)
            String orderId = "12345678"; // 订单号

            System.out.println("  原始参数:");
            System.out.println("    设备注册号(bytes): " + Str2HexUtils.bytesToHex(deviceRegId));
            System.out.println("    设备序列号(int): 0x" + String.format("%06X", deviceSerialNo));
            System.out.println("    农户注册号: " + Str2HexUtils.bytesToHex(farmerRegId));
            System.out.println("    充值金额: " + rechargeAmount + "分");
            System.out.println("    订单号: " + orderId);

            // 创建上行充值报文
            RechargeMessage.Uplink uplink = new RechargeMessage.Uplink(deviceRegId, deviceSerialNo, farmerRegId, rechargeAmount, orderId);

            // 测试toString方法
            System.out.println("  Uplink.toString(): " + uplink.toString());
            ctx.writeAndFlush(uplink);

        }catch (Exception exception){
            exception.printStackTrace();
        }
        }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Message msg) throws Exception {
        log.info("收到服务器消息: {}", msg.toString());

        if (msg instanceof RegisterMessage) {
            handlerRegister(ctx, msg);
        } else if (msg instanceof RegisterConfirmMessage) {
            handlerRegisterConfirm(ctx, msg);
        } else if (msg instanceof BalanceQueryMessage) {
            handlerBalanceQuery(ctx, (BalanceQueryMessage) msg);
        } else if (msg instanceof RechargeMessage) {
            handlerRechargeMessage(ctx, (RechargeMessage) msg);
        } else if (msg instanceof OpenCardMessage) {
            handleOpenCardMessage(ctx, (OpenCardMessage) msg);
        } else if (msg instanceof WaterElectricityPriceQueryMessage) {
            handleWaterElectricityPriceQueryMessage(ctx, (WaterElectricityPriceQueryMessage) msg);
        } else {
            handleOtherMessage(ctx, msg);
        }
    }

    private void handlerRechargeMessage(ChannelHandlerContext ctx, RechargeMessage msg) {
        log.info("收到充值报文");
        if (msg instanceof RechargeMessage.Downlink) {
            log.info("==充值下行报文=======");
            RechargeMessage.Downlink downlink = (RechargeMessage.Downlink) msg;
            log.info("充值下行报文内容: {}", downlink.toString());
            log.info("状态码: 0x{}", String.format("%02X", downlink.getStatusCodeBCD()));
            log.info("充值金额: {}分", downlink.getBalance());
            log.info("交易流水号: {}", downlink.getOrderNoString());
        } else if (msg instanceof RechargeMessage.Uplink) {
            log.info("==充值上行报文=======");
            RechargeMessage.Uplink uplink = (RechargeMessage.Uplink) msg;
            log.info("充值上行报文内容: {}", uplink.toString());
        } else {
            log.info("==充值未知类型报文=======");
            log.info("报文类型: {}", msg.getClass().getName());
        }
    }

    private void handlerBalanceQuery(ChannelHandlerContext ctx, BalanceQueryMessage msg) {
        log.info("收到余额查询响应报文");
        if (msg instanceof BalanceQueryMessage.Downlink) {
            log.info("==余额查询下行报文=======");
            //下行
            BalanceQueryMessage.Downlink downlink = (BalanceQueryMessage.Downlink) msg;
            log.info("余额查询下行报文内容: {}", downlink.toString());
            log.info("状态码: 0x{}", String.format("%02X", downlink.getStatusCodeBCD()));
            log.info("余额: {}分", downlink.getMoneyValue());
            log.info("用户名: {}", downlink.getUsername());
            log.info("卡号: {}", downlink.getCardNO());
        } else if (msg instanceof BalanceQueryMessage.Uplink) {
            //上行
            log.info("==余额查询上行报文=======");
            BalanceQueryMessage.Uplink uplink = (BalanceQueryMessage.Uplink) msg;
            log.info("余额查询上行报文内容: {}", uplink.toString());
        } else {
            // 未知类型
            log.info("==余额查询未知类型报文=======");
            log.info("报文类型: {}", msg.getClass().getName());
        }
    }

    private void handlerRegister(ChannelHandlerContext ctx, Message msg) {
        if(msg.getControl()==FrameConstants.CONTROL_DOWNLINK){
            log.info("==注册下行报文=======");
            //下行
            RegisterMessage.Downlink downlink=( RegisterMessage.Downlink)msg;
            log.info("注册下行报文内容: {}", downlink.toString());
        }else{
            //上行
            log.info("==上行报文=======");
            RegisterMessage.Uplink uplink=( RegisterMessage.Uplink)msg;
            log.info("注册上行报文内容: {}", uplink.toString());
        }
    }

    private void handlerRegisterConfirm(ChannelHandlerContext ctx, Message msg) {
        if (msg.getControl() == FrameConstants.CONTROL_DOWNLINK) {
            log.info("==注册确认下行报文=======");
            RegisterConfirmMessage.Downlink downlink = (RegisterConfirmMessage.Downlink) msg;
            log.info("注册确认下行报文内容: {}", downlink.toString());
        } else {
            log.info("==注册确认上行报文=======");
            RegisterConfirmMessage.Uplink uplink = (RegisterConfirmMessage.Uplink) msg;
            log.info("注册确认上行报文内容: {}", uplink.toString());
        }
    }

//    /**
//     * 处理注册响应报文
//     */
//    private void handleRegisterAckMessage(ChannelHandlerContext ctx, RegisterAckMessage msg) {
//        regId = msg.getRegIdString();
//        regIdArr=msg.getUserData();
//        registered = true;
//
//        log.info("注册成功！获得设备注册号: {}", regId);
//
//        // 注册成功后启动心跳
////        startHeartbeat(ctx);
//        //手持终端设备注册确认
//        sengRegConfirm(ctx,msg);
//        // 可以在这里发送其他业务报文，例如余额查询
//        sendBalanceQuery(ctx);
//    }
//
    //注册确认报文
    private void sengRegConfirm(ChannelHandlerContext ctx, RegisterConfirmMessage msg) {
        ctx.writeAndFlush(msg);
        log.info("已发送注册确认报文");
    }

    /**
     * 处理心跳报文
     */
//    private void handleHeartbeatMessage(ChannelHandlerContext ctx, HeartbeatMessage msg) {
//        if (!msg.isUplink()) {
//            log.debug("收到服务器心跳响应");
//        }
//    }

    /**
     * 处理开卡下行报文
     */
    private void handleOpenCardMessage(ChannelHandlerContext ctx, OpenCardMessage msg) {
        log.info("----开卡报文解析------");
        if (msg instanceof OpenCardMessage.Downlink) {
            log.info("==开卡下行报文=======");
            OpenCardMessage.Downlink downlink = (OpenCardMessage.Downlink) msg;
            log.info("开卡下行报文内容: {}", downlink.toString());
            log.info("状态码: 0x{}", String.format("%02X", downlink.getStatus()));
            log.info("订单号: {}", downlink.getOrderId());
            log.info("卡号: {}", HexUtil.encodeHexStr(downlink.getFarmerId()));
        } else if (msg instanceof OpenCardMessage.Uplink) {
            log.info("==开卡上行报文=======");
            OpenCardMessage.Uplink uplink = (OpenCardMessage.Uplink) msg;
            log.info("开卡上行报文内容: {}", uplink.toString());
        } else {
            log.info("==开卡未知类型报文=======");
            log.info("报文类型: {}", msg.getClass().getName());
        }
    }

    /**
     * 处理阶梯水电价查询报文
     */
    private void handleWaterElectricityPriceQueryMessage(ChannelHandlerContext ctx, WaterElectricityPriceQueryMessage msg) {
        log.info("----阶梯水电价查询报文解析------");
        if (msg instanceof WaterElectricityPriceQueryMessage.Downlink) {
            log.info("==阶梯水电价查询下行报文=======");
            WaterElectricityPriceQueryMessage.Downlink downlink = (WaterElectricityPriceQueryMessage.Downlink) msg;
            log.info("阶梯水电价查询下行报文内容: {}", downlink.toString());
            log.info("状态码: 0x{}", String.format("%02X", downlink.getStatusCodeBCD()));
            log.info("1阶水价: {}元", downlink.getWaterPrice1Value());
            log.info("2阶水价: {}元", downlink.getWaterPrice2Value());
            log.info("3阶水价: {}元", downlink.getWaterPrice3Value());
            log.info("1阶电价: {}元", downlink.getTieredPrice1Value());
            log.info("2阶电价: {}元", downlink.getTieredPrice2Value());
            log.info("3阶电价: {}元", downlink.getTieredPrice3Value());
        } else if (msg instanceof WaterElectricityPriceQueryMessage.Uplink) {
            log.info("==阶梯水电价查询上行报文=======");
            WaterElectricityPriceQueryMessage.Uplink uplink = (WaterElectricityPriceQueryMessage.Uplink) msg;
            log.info("阶梯水电价查询上行报文内容: {}", uplink.toString());
        } else {
            log.info("==阶梯水电价查询未知类型报文=======");
            log.info("报文类型: {}", msg.getClass().getName());
        }
    }

    /**
     * 处理其他类型的报文
     */
    private void handleOtherMessage(ChannelHandlerContext ctx, Message msg) {
        log.info("收到其他类型报文，AFN: 0x{}", String.format("%02X", msg.getAfn()));
        log.info("报文内容: {}", msg.toString());
    }

    /**
     * 发送注册报文
     */
    private void sendRegisterMessage(ChannelHandlerContext ctx) {
        RegisterMessage.Uplink uplink =new RegisterMessage.Uplink(clientAddress);
        ctx.writeAndFlush(uplink);
        log.info("已发送注册报文");
    }

    /**
     * 发送余额查询报文（示例）
     */
    private void sendBalanceQuery(ChannelHandlerContext ctx) {
        // 创建20字节地址域的余额查询报文
        int deviceSerialNo=667890;
        /**
         *       deviceRegId 设备注册号 (16字节)
         *       deviceSerialNo 充值管理机序列号 (int类型) 3字节
         *       farmerRegistrationId 农户注册编号 (16字节)
         */
        //设备注册号 16个字节 低位在前 高位在后
        byte[] deviceRegIdBytes = new byte[16];
        // 使用16字节的设备注册号和int类型的设备序列号创建上行余额查询报文
        // 设备注册号 (16字节，低位在前)
        for (int i = 0; i < 16; i++) {
            deviceRegIdBytes[i] = (byte) (i + 1);
        }

        //农户注册编号,16个字节 低位在前 高位在后
        byte[] farmerRegistrationIdBytes=new byte[16];
        // 创建农户注册号 (16字节，低位在前)
        for (int i = 0; i < 16; i++) {
            farmerRegistrationIdBytes[i] = (byte) (i + 10);
        }

        System.out.println("  农户注册号: " + Str2HexUtils.bytesToHex(farmerRegistrationIdBytes));

        BalanceQueryMessage.Uplink queryMsg =
                new BalanceQueryMessage.Uplink(deviceRegIdBytes, deviceSerialNo, farmerRegistrationIdBytes);
        ctx.writeAndFlush(queryMsg);
        log.info("已发送余额查询报文");
    }

    /**
     * 启动心跳任务
     */
//    private void startHeartbeat(ChannelHandlerContext ctx) {
//        if (heartbeatTask != null) {
//            heartbeatTask.cancel(false);
//        }
//
//        heartbeatTask = ctx.executor().scheduleAtFixedRate(() -> {
//            if (ctx.channel().isActive()) {
//                HeartbeatMessage heartbeat = HeartbeatMessage.createUplink(clientAddress);
//                ctx.writeAndFlush(heartbeat);
//                log.debug("发送心跳报文");
//            }
//        }, 30, 30, TimeUnit.SECONDS);
//
//        log.info("心跳任务已启动，间隔30秒");
//    }

    /**
     * 停止心跳任务
     */
    private void stopHeartbeat() {
        if (heartbeatTask != null) {
            heartbeatTask.cancel(false);
            heartbeatTask = null;
            log.info("心跳任务已停止");
        }
    }

//    @Override
//    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
//        if (evt instanceof IdleStateEvent) {
//            IdleStateEvent event = (IdleStateEvent) evt;
//            if (event.state() == IdleState.WRITER_IDLE) {
//                // 写空闲时发送心跳
//                if (registered) {
//                    HeartbeatMessage heartbeat = HeartbeatMessage.createUplink(clientAddress);
//                    ctx.writeAndFlush(heartbeat);
//                    log.debug("写空闲触发，发送心跳报文");
//                }
//            } else if (event.state() == IdleState.ALL_IDLE) {
//                log.warn("连接空闲超时，关闭连接");
//                ctx.close();
//            }
//        }
//        super.userEventTriggered(ctx, evt);
//    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.warn("与服务器的连接已断开");
        stopHeartbeat();
        registered = false;
        deviceId = null;
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("客户端发生异常", cause);
        ctx.close();
    }

    // Getters
    public boolean isRegistered() {
        return registered;
    }

    public String getDeviceId() {
        return deviceId;
    }

    public String getClientAddressString() {
        StringBuilder sb = new StringBuilder();
        for (byte b : clientAddress) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString().trim();
    }
}
